﻿namespace Smark.Core
{
    using System;
    using System.Security.Cryptography;
    using System.Text;

    public class RasCrypto
    {
        private RSACryptoServiceProvider rsaProvider;

        public RasCrypto()
        {
            this.rsaProvider = new RSACryptoServiceProvider(0x400);
        }

        public RasCrypto(int bit)
        {
            this.rsaProvider = new RSACryptoServiceProvider(bit);
        }

        public void CopyRSAParameters(bool includePrivateParameters, RasCrypto rsa)
        {
            RSAParameters parameters = this.rsaProvider.ExportParameters(includePrivateParameters);
            rsa.rsaProvider.ImportParameters(parameters);
        }

        public string Decrypt(string data)
        {
            return Encoding.UTF8.GetString(this.Decrypt(Convert.FromBase64String(data)));
        }

        public byte[] Decrypt(byte[] data)
        {
            return this.rsaProvider.Decrypt(data, false);
        }

        public byte[] Encrypt(byte[] data)
        {
            return this.rsaProvider.Encrypt(data, false);
        }

        public string Encrypt(string data)
        {
            return Convert.ToBase64String(this.Encrypt(Encoding.UTF8.GetBytes(data)));
        }

        public RSAParameters ExportParameters(bool includePrivateParameters)
        {
            return this.rsaProvider.ExportParameters(includePrivateParameters);
        }

        public string GetRSAParametersData(bool includePrivateParameters)
        {
            RSAParameters parameters = this.rsaProvider.ExportParameters(includePrivateParameters);
            StringBuilder builder = new StringBuilder();
            builder.Append((parameters.D != null) ? Convert.ToBase64String(parameters.D) : "").Append("\n");
            builder.Append((parameters.DP != null) ? Convert.ToBase64String(parameters.DP) : "").Append("\n");
            builder.Append((parameters.DQ != null) ? Convert.ToBase64String(parameters.DQ) : "").Append("\n");
            builder.Append((parameters.Exponent != null) ? Convert.ToBase64String(parameters.Exponent) : "").Append("\n");
            builder.Append((parameters.InverseQ != null) ? Convert.ToBase64String(parameters.InverseQ) : "").Append("\n");
            builder.Append((parameters.Modulus != null) ? Convert.ToBase64String(parameters.Modulus) : "").Append("\n");
            builder.Append((parameters.P != null) ? Convert.ToBase64String(parameters.P) : "").Append("\n");
            builder.Append((parameters.Q != null) ? Convert.ToBase64String(parameters.Q) : "").Append("\n");
            return builder.ToString();
        }

        public void ImportParameters(RSAParameters parameters)
        {
            this.rsaProvider.ImportParameters(parameters);
        }

        public void SetRSAParameters(string data)
        {
            RSAParameters parameters = new RSAParameters();
            string[] strArray = data.Split(new char[] { '\n' });
            parameters.D = string.IsNullOrEmpty(strArray[0]) ? null : Convert.FromBase64String(strArray[0]);
            parameters.DP = string.IsNullOrEmpty(strArray[1]) ? null : Convert.FromBase64String(strArray[1]);
            parameters.DQ = string.IsNullOrEmpty(strArray[2]) ? null : Convert.FromBase64String(strArray[2]);
            parameters.Exponent = string.IsNullOrEmpty(strArray[3]) ? null : Convert.FromBase64String(strArray[3]);
            parameters.Modulus = string.IsNullOrEmpty(strArray[4]) ? null : Convert.FromBase64String(strArray[4]);
            parameters.Modulus = string.IsNullOrEmpty(strArray[5]) ? null : Convert.FromBase64String(strArray[5]);
            parameters.P = string.IsNullOrEmpty(strArray[6]) ? null : Convert.FromBase64String(strArray[6]);
            parameters.Q = string.IsNullOrEmpty(strArray[7]) ? null : Convert.FromBase64String(strArray[7]);
            this.rsaProvider.ImportParameters(parameters);
        }

        public byte[] Sign(byte[] data)
        {
            return this.rsaProvider.SignData(data, "MD5");
        }

        public string Sign(string data)
        {
            return Convert.ToBase64String(this.Sign(Encoding.ASCII.GetBytes(data)));
        }

        public bool Verify(byte[] data, byte[] Signature)
        {
            return this.rsaProvider.VerifyData(data, "MD5", Signature);
        }

        public bool Verify(string data, string signature)
        {
            return this.Verify(Encoding.ASCII.GetBytes(data), Convert.FromBase64String(signature));
        }

        public string PrivateKey
        {
            get
            {
                return this.rsaProvider.ToXmlString(true);
            }
            set
            {
                this.rsaProvider.FromXmlString(value);
            }
        }

        public string PublicKey
        {
            get
            {
                return this.rsaProvider.ToXmlString(false);
            }
            set
            {
                this.rsaProvider.FromXmlString(value);
            }
        }
    }
}

